package cn.source.web.controller.dingdingWeb;
import cn.hutool.core.bean.BeanUtil;
import cn.source.common.core.domain.AjaxResult;
import cn.source.system.common.domain.vo.JsonResult;
import cn.source.system.dingding.config.DingAppConfig;
import cn.source.system.dingding.config.DingUrlConstant;
import cn.source.system.dingding.domain.ConfigDTO;
import cn.source.system.dingding.exception.DingtalkEncryptException;
import cn.source.system.dingding.util.JsApiSignature;
import cn.source.system.dingding.domain.ServiceResult;
import cn.source.system.dingding.domain.UserDto;
import cn.source.system.dingding.service.DingAuthService;
import cn.source.system.dingding.service.DingDingTokenService;
import cn.source.system.module.entity.DailyViewUser;
import cn.source.system.organization.entity.User;
import com.alibaba.fastjson.JSONObject;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiUserGetRequest;
import com.dingtalk.api.request.OapiUserGetuserinfoRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.request.OapiV2UserGetuserinfoRequest;
import com.dingtalk.api.response.OapiUserGetResponse;
import com.dingtalk.api.response.OapiUserGetuserinfoResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.dingtalk.api.response.OapiV2UserGetuserinfoResponse;
import com.taobao.api.ApiException;
import io.swagger.annotations.ApiOperation;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.Optional;
@RestController
@RequestMapping("/system/dingding")
@Log4j2
public class DingDingLoginController {
    @Autowired
    private DingDingTokenService dingDingTokenService;
    @Autowired
    private DingAuthService dingAuthService;
    @Resource
    private DingAppConfig dingAppConfig;
    /**
     * 钉钉用户登录，显示当前登录用户的userId和名称
     *
     * @param authCode 免登录的临时授权码
     * @param request
     * @return
     */
    @ApiOperation("钉钉用户登录，显示当前登录用户的userId和名称")
    @PostMapping("/avoidLogin")
    public JsonResult avoidLogin(@RequestBody String authCode, HttpServletRequest request) {
        String accessToken;
        System.out.println(authCode);
        ServiceResult<String> accessTokenSr = dingDingTokenService.getAccessToken();
        if (!accessTokenSr.isSuccess()) {
            return JsonResult.fail(Integer.parseInt(accessTokenSr.getCode()), accessTokenSr.getMessage());
        }
        accessToken = accessTokenSr.getResult();
        JSONObject jsonObject = JSONObject.parseObject(authCode);
        String getAuthCode = (String) jsonObject.get("authCode");
        // 获取用户userId
        ServiceResult<String> userIdSr = getUserInfo(accessToken, getAuthCode);
        if (!userIdSr.isSuccess()) {
            return JsonResult.fail(Integer.parseInt(userIdSr.getCode()), userIdSr.getMessage());
        }
        // 获取用户详情
        JsonResult userInfo = this.getUser(accessToken, userIdSr.getResult());
        UserDto userDTO = (UserDto) userInfo.getResult();
        log.info("根据accessToken和用户userId查询出的用户信息 userDTO = {}", userDTO);
        HttpSession session = request.getSession();
        DailyViewUser user = this.getUserFromUserDTO(userDTO);
        session.setAttribute("date", String.valueOf(System.currentTimeMillis()));
        session.setAttribute("user", user);
        return userInfo;
    }
    private DailyViewUser getUserFromUserDTO(UserDto userDto) {
        DailyViewUser user = new DailyViewUser();
        user.setTrueName(userDto.getTrueName());
        user.setUserId(userDto.getUserId());
        user.setDingUserId(userDto.getDingUserId());
        user.setHandset(userDto.getHandset());
        user.setIsAdmin(userDto.getIsAdmin());
        user.setIsLeader(userDto.getIsLeader());
        user.setPosition(userDto.getPosition());
        user.setUserLevel(userDto.getUserLevel());
        user.setUserState(userDto.getUserState());
        return user;
    }
    private ServiceResult<String> getUserInfo(String accessToken, String authCode) {
        DingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_GET_USER_INFO);
        OapiUserGetuserinfoRequest request = new OapiUserGetuserinfoRequest();
        request.setCode(authCode);
        request.setHttpMethod("GET");
        OapiUserGetuserinfoResponse response;
        try {
            response = client.execute(request, accessToken);
        } catch (ApiException e) {
            log.error("Failed to {}", DingUrlConstant.URL_GET_USER_INFO, e);
            return ServiceResult.failure(e.getErrCode(), "Failed to getUserInfo: " + e.getErrMsg());
        }
        if (!response.isSuccess()) {
            return ServiceResult.failure(response.getErrorCode(), response.getErrmsg());
        }
        return ServiceResult.success(response.getUserid());
    }
    private JsonResult getUser(String accessToken, String userId) {
        DingTalkClient client = new DefaultDingTalkClient(DingUrlConstant.URL_USER_GET);
        OapiUserGetRequest request = new OapiUserGetRequest();
        request.setUserid(userId);
        request.setHttpMethod("GET");
        OapiUserGetResponse response;
        try {
            response = client.execute(request, accessToken);
        } catch (ApiException e) {
            log.error("Failed to {}", DingUrlConstant.URL_USER_GET, e);
            return JsonResult.fail(Integer.parseInt(e.getErrCode()), "Failed to getUserName: " + e.getErrMsg());
        }
        UserDto user = this.assembleUserDTO(response, accessToken);
        return JsonResult.ok(user);
    }
    private UserDto assembleUserDTO(OapiUserGetResponse response, String accessToken) {
        UserDto user = new UserDto();
        String userid = response.getUserid();
        String mobile = response.getMobile();
        try {
            DailyViewUser dailyViewUser = Optional.ofNullable(dingAuthService.getUserByUserId(userid))
                .orElse(dingAuthService.getUserByUsername(mobile));
            BeanUtil.copyProperties(dailyViewUser, user);
            user.setAccessToken(accessToken);
            user.setName(response.getName());
            user.setAvatar(response.getAvatar());
        } catch (Exception e) {
            log.error("E|DingAuthController|assembleUserDTO()|根据用户钉钉userId或者用户钉钉手机号mobile查询用户信息失败！");
        }
        return user;
    }
    @ApiOperation(value = "钉钉配置接口")
    @PostMapping("/config")
    @ResponseBody
    public JsonResult config(HttpServletRequest request) {
        ConfigDTO config = new ConfigDTO();
        String url = request.getRequestURL().toString();
        String queryString = request.getQueryString();
        if (queryString != null) {
            url = url + queryString;
        }
        ServiceResult<String> jsTicketSr = dingDingTokenService.getJsTicket();
        if (!jsTicketSr.isSuccess()) {
            return JsonResult.fail(Integer.parseInt(jsTicketSr.getCode()), jsTicketSr.getMessage());
        }
        config.setAgentId(dingAppConfig.getAgentId());
        config.setCorpId(dingAppConfig.getCorpId());
        config.setJsticket(jsTicketSr.getResult());
        config.setNonceStr(JsApiSignature.genNonce());
        config.setTimeStamp(System.currentTimeMillis() / 1000);
        String sign;
        try {
            sign = JsApiSignature.sign(url, config.getNonceStr(), config.getTimeStamp(), config.getJsticket());
        } catch (DingtalkEncryptException e) {
            return JsonResult.fail(e.getCode(), e.getMessage());
        }
        config.setSignature(sign);
        return JsonResult.ok(config);
    }
    @ApiOperation("获取当前登录用户信息")
    @GetMapping(value = "/getUserInfo/{authCode}")
    public JsonResult getUserInfo(@PathVariable String authCode){
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
            OapiV2UserGetuserinfoRequest req = new OapiV2UserGetuserinfoRequest();
            req.setCode(authCode);
            System.out.println(authCode);
            String accessToken;
            ServiceResult<String> accessTokenSr = dingDingTokenService.getAccessToken();
            if (!accessTokenSr.isSuccess()) {
                return JsonResult.fail(Integer.parseInt(accessTokenSr.getCode()), accessTokenSr.getMessage());
            }
            accessToken = accessTokenSr.getResult();
            OapiV2UserGetuserinfoResponse rsp = client.execute(req, accessToken);
            return JsonResult.ok(rsp.getResult());
        } catch (ApiException e) {
            e.printStackTrace();
            return JsonResult.fail(String.valueOf(e));
        }
    }
    @ApiOperation("获取用户超级无敌详细的信息")
    @GetMapping("/v2/user/{authCode}")
    private JsonResult getV2User(@PathVariable String authCode){
        System.out.println(11111);
        try {
            DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
            DingTalkClient client1 = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/getuserinfo");
            OapiV2UserGetRequest req = new OapiV2UserGetRequest();
            OapiV2UserGetuserinfoRequest req1 = new OapiV2UserGetuserinfoRequest();
            DailyViewUser user=new DailyViewUser();
            String accessToken;
            req1.setCode(authCode);
            ServiceResult<String> accessTokenSr = dingDingTokenService.getAccessToken();
            if (!accessTokenSr.isSuccess()) {
                return JsonResult.fail(Integer.parseInt(accessTokenSr.getCode()), accessTokenSr.getMessage());
            }
            accessToken = accessTokenSr.getResult();
            OapiV2UserGetuserinfoResponse rsp1 = client1.execute(req1, accessToken);
            req.setUserid(rsp1.getResult().getUserid());
            OapiV2UserGetResponse rsp = client.execute(req, accessToken);
            System.out.println(dingAuthService.exitUserInfo(rsp1.getResult().getUserid()));
            if(dingAuthService.exitUserInfo(rsp1.getResult().getUserid()).isEmpty()){
                user.setDingUserId(rsp.getResult().getUserid());
                user.setHandset(rsp.getResult().getMobile());
                user.setTrueName(rsp.getResult().getName());
                user.setIsAdmin(rsp.getResult().getBoss());
                user.setUserLevel(rsp1.getResult().getSysLevel());
                user.setUnionId(rsp1.getResult().getUnionid());
                user.setPosition(rsp.getResult().getTitle());
                dingAuthService.insertUserInfo(user);
            }
            if(rsp.getResult().getTitle()!=dingAuthService.selectUserInfo(rsp.getResult().getUserid()).getPosition()){
                dingAuthService.updateUserPosition( rsp.getResult().getUserid(),rsp.getResult().getTitle());
            }
            return JsonResult.ok(rsp.getResult());
        } catch (ApiException e) {
            return JsonResult.fail(String.valueOf(e));
        }
    }
}
